package com.bonc.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.logging.nologging.NoLoggingImpl;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @ClassName DynamicDataSourceConfig
 * @Description: 数据源配置类
 * @Author chenGJ
 * @Date 2021/12/21 10:01
 * @Version V1.0
**/
@Configuration
public class DynamicDataSourceConfig {

    @Autowired
    private Environment env;

    @Value("${mybatis.type.aliases.package}")
    private String typeAliasesPackage;

    @Value("${mybatis.mapper.locations}")
    private String locations;

    @Value("${spring.datasource.datasourceNames}")
    private String datasourceNames;

    /**
     * 默认数据源
     * @return
     */
    @Bean(name = "defaultDataSource")
    @ConfigurationProperties("spring.datasource.druid.default")
    public DataSource defaultDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 已经配置的动态数据源。
     */
    private Map<Object, Object> getDataSources() {
        Map<Object, Object> map = new HashMap<>(5);
        if (datasourceNames != null && datasourceNames.length() > 0) {
            String[] names = datasourceNames.split(",");
            for (String name : names) {
                DruidDataSource dataSource = new DruidDataSource();
                dataSource.setUrl(env.getProperty("spring.datasource.druid." + name + ".url"));
                dataSource.setUsername(env.getProperty("spring.datasource.druid." + name + ".username"));
                dataSource.setPassword(env.getProperty("spring.datasource.druid." + name + ".password"));
                dataSource.setDriverClassName(env.getProperty("spring.datasource.druid." + name + ".driver-class-name"));
                dataSource.setBreakAfterAcquireFailure(true);
                dataSource.setConnectionErrorRetryAttempts(0);
                map.put(name, dataSource);
            }
        }
        return map;
    }

    /**
     * 初始化动态数据源
     */
    @Bean(name = "dynamicDataSource")
    @Primary
    public DataSource dynamicDataSource(@Qualifier("defaultDataSource") DataSource defaultDataSource){
        Map<Object,Object> targetDataSources = this.getDataSources();
        targetDataSources.put(DataSourceNames.DEFAULT,defaultDataSource);
        return new DynamicDataSource(defaultDataSource,targetDataSources);
    }


    /**
     * 动态数据源的session工厂
     * @param dynamicDataSource
     * @return SqlSessionFactory
     * @throws Exception
     */
    @Bean(name = "defaultSqlSessionFactory")
    @Primary
    public SqlSessionFactory defaultSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource)throws Exception
    {
        //数据源
        SqlSessionFactoryBean defaultBean = new SqlSessionFactoryBean();
        defaultBean.setDataSource(dynamicDataSource);
        // 扫描Model
        defaultBean.setTypeAliasesPackage(typeAliasesPackage);
        //xml文件
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        defaultBean.setMapperLocations(resolver.getResources(locations));
        //配置
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
//        configuration.setLogImpl(StdOutImpl.class);
//        configuration.setLogImpl(NoLoggingImpl.class);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCallSettersOnNulls(true);
        defaultBean.setConfiguration(configuration);
        //mysql分页插件
        Properties props = new Properties();
        props.setProperty("helperDialect", "mysql");
        props.setProperty("reasonable", "true");
        props.setProperty("supportMethodsArguments", "true");
        props.setProperty("params", "count=countSql");
        //oracle分页插件
        Interceptor interceptorDefault = new PageInterceptor();
        interceptorDefault.setProperties(props);
        Interceptor interceptorOracle = new PageInterceptor();
        props.setProperty("helperDialect","oracle");
        interceptorOracle.setProperties(props);
        defaultBean.setPlugins(new Interceptor[] {interceptorDefault,interceptorOracle});
        return defaultBean.getObject();
    }

    /**
     * 动态数据源事务管理器
     * @param dynamicDataSource
     * @return DataSourceTransactionManager
     * @throws Exception
     */
    @Bean
    @Primary
    public DataSourceTransactionManager defaultDataSourceTransactionManager(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) throws Exception{
        return new DataSourceTransactionManager(dynamicDataSource);
    }
}

